<template>
  <BasicDrawer
    v-bind="$attrs"
    @register="registerDrawer"
    :title="getTitle"
    width="500px"
    @ok="handleSubmit"
  >
    <BasicForm @register="registerForm">
      <template #btnAdd>
        <a-button
          style="margin-left: 25px"
          type="primary"
          @click="btnAddAccess"
          :loading="unref(isUpdate)"
          >新增权限</a-button
        >
      </template>
      <template #btnEdit>
        <a-button
          style="margin-left: 25px"
          type="primary"
          @click="btnEditAccess"
          :loading="unref(isUpdate)"
          >保存</a-button
        >
      </template>
      <template #btnCancel>
        <a-button style="margin-left: 25px" @click="btnCancel" v-if="!!treeData.length"
          >取消</a-button
        >
      </template>
      <template #menu>
        <BasicTree
          v-model:value="model[field]"
          ref="treeRef"
          :treeData="treeData"
          :fieldNames="{ key: 'id', extendField: 'auth_code' }"
          :actionList="actionList"
          isExpandAll
          title="权限列表"
        >
          <template #customLab="{ name, auth_code }">
            <span>{{ name }} ({{ auth_code }})</span>
          </template>
        </BasicTree>
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
<script lang="ts">
  import { defineComponent, ref, computed, unref, h } from 'vue';
  import { BasicForm, useForm } from '@/components/Form/index';
  import { formAccess, accessForm, aAuthCode } from './menu.data';
  import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  import { useMessage } from '@/hooks/web/useMessage';

  import { BasicTree, TreeActionItem, TreeActionType, TreeItem } from '@/components/Tree';

  import { getAccessList, addAccessItem, editAccessItem, delAccessItem } from '@/api/system/system';
  import { DeleteOutlined, PlusOutlined, EditOutlined } from '@ant-design/icons-vue';
  import { cloneDeep, forEach, isArray } from 'lodash-es';

  export default defineComponent({
    name: 'RoleDrawer',
    components: { BasicDrawer, BasicForm, BasicTree },
    emits: ['success', 'register'],
    setup(_, { emit }) {
      const treeRef = ref<Nullable<TreeActionType>>(null);

      const isUpdate = ref(false);
      const nAtRowId = ref(-1);
      const nEditType = ref('1');
      const treeData = ref<TreeItem[]>([]);
      const { createConfirm } = useMessage();
      const [registerForm, { resetFields, setFieldsValue, validate, updateSchema }] = useForm({
        labelWidth: 90,
        schemas: formAccess,
        showActionButtonGroup: false,
        baseColProps: { lg: 12, md: 24 },
      });

      const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
        resetFields();
        setDrawerProps({ confirmLoading: false });
        // 需要在setFieldsValue之前先填充treeData，否则Tree组件可能会报key not exist警告
        // 每次都请求最新的数据
        nAtRowId.value = data.record.id;
        treeData.value = (await getAccessList({ menu_id: data.record.id }))[
          'list'
        ] as any as TreeItem[];
        nEditType.value = '1';
        let setValue;
        if (unref(treeData).length) {
          setValue = {
            btn_edit: '',
          };
        } else {
          nEditType.value = '3';
          setValue = {
            btn_edit: '-1',
            parent_id: '0',
            menu_id: data.record.id,
          };
        }
        setFieldsValue({
          ...setValue,
        });

        updateSchema([
          {
            field: 'auth_code',
            componentProps: {
              options: [...aAuthCode],
            },
          },
        ]);
      });
      function expandAll(checkAll: boolean) {
        getTree().expandAll(checkAll);
      }
      function getTree() {
        const tree = unref(treeRef);
        if (!tree) {
          throw new Error('tree is null!');
        }
        return tree;
      }

      const getTitle = computed(
        () =>
          (unref(nEditType) === '1' && '权限详情') ||
          (unref(nEditType) === '2' && '修改权限') ||
          (unref(nEditType) === '3' && '新增权限'),
      );

      async function handleSubmit() {
        try {
          const values = await validate();
          setDrawerProps({ confirmLoading: true });
          // TODO custom api
          console.log(values);
          closeDrawer();
          emit('success');
        } finally {
          setDrawerProps({ confirmLoading: false });
        }
      }
      const actionList: TreeActionItem[] = [
        {
          // show:()=>boolean;
          render: (node) => {
            // 编辑
            return h(EditOutlined, {
              class: 'ml-2',
              onClick: () => {
                btnEditAccessItem(node);
              },
            });
          },
        },
        {
          // show:()=>boolean;
          render: (node) => {
            // 新增
            return h(PlusOutlined, {
              class: 'ml-2',
              onClick: () => {
                btnAddAccessItem(node);
              },
            });
          },
        },
        {
          render: (node) => {
            return h(DeleteOutlined, {
              onClick: () => {
                delAccessMenu(node);
              },
            });
          },
        },
      ];

      function delAccessMenu(node: any) {
        createConfirm({
          iconType: 'error',
          title: '删除按钮',
          content: '确定要删除当前按钮吗，请谨慎使用！',
          onOk: async () => {
            setDrawerProps({ loading: true });
            const codeData = await delAccessItem({ ids: node.id.toString() });
            console.log(codeData);
            // if (codeData == 200) {
            treeData.value = (
              await getAccessList({
                menu_id: node.menu_id,
              })
            )['list'] as any as TreeItem[];
            setDrawerProps({ loading: false });
            // }
          },
        });
      }

      function btnEditAccessItem(node: any) {
        nEditType.value = '2';
        let accessItem: any = cloneDeep(accessForm);
        forEach(accessItem, (_v, k) => {
          accessItem[k] = node[k];
        });
        if (accessItem.auth_code.indexOf('other') >= 0) {
          accessItem.auth_code_e = accessItem.auth_code.replace('other', '');
          accessItem.auth_code = 'other';
        }
        if (accessItem.auth_code.indexOf('tags') >= 0) {
          accessItem.auth_code_o = accessItem.auth_code.replace('tags', '');
          accessItem.auth_code = 'tags';
        }
        accessItem.btn_edit = '-1';

        setFieldsValue({
          ...accessItem,
        });
        fnFiltrateCode(node);
      }

      function btnAddAccess() {
        btnAddAccessItem({ menu_id: unref(nAtRowId), id: 0, parent_id: 0, auth_code: '' });
      }

      function btnAddAccessItem(node: any) {
        nEditType.value = '3';
        resetFields();
        setFieldsValue({
          menu_id: node.menu_id,
          btn_edit: '-1',
          parent_id: node.id,
        });

        fnFiltrateCode(node, false);
      }
      function btnCancel() {
        nEditType.value = '1';
        setFieldsValue({
          btn_edit: '',
        });
        setTimeout(() => {
          expandAll(true);
        }, 100);
      }

      async function btnEditAccess() {
        // resetFields();
        const values = cloneDeep(await validate());
        console.log(values, 'values');
        values.id ? (values.id = parseInt(values.id)) : '';
        values.parent_id ? (values.parent_id = parseInt(values.parent_id)) : '';
        values.menu_id ? (values.menu_id = parseInt(values.menu_id)) : '';
        values.is_show ? (values.is_show = parseInt(values.is_show)) : '';

        if (values.auth_code == 'other') {
          values.auth_code = values.auth_code + values.auth_code_e;
        }
        if (values.auth_code == 'tags') {
          values.auth_code = values.auth_code + values.auth_code_o;
        }

        isUpdate.value = true;
        if (nEditType.value === '3') delete values.id;
        delete values.btn_edit;
        // const codeData =
        nEditType.value === '3' ? await addAccessItem(values) : await editAccessItem(values);
        treeData.value = (await getAccessList({ menu_id: values.menu_id }))[
          'list'
        ] as any as TreeItem[];
        // if (codeData === 200) {
        isUpdate.value = false;
        setFieldsValue({
          btn_edit: '',
        });
        setTimeout(() => {
          expandAll(true);
        }, 100);
        // }
      }

      function fnFiltrateCode(node, isEdit = true) {
        let aFindList = fnFindPidList(unref(treeData), node.parent_id);
        let tempList = cloneDeep(aAuthCode);
        tempList.forEach((v: any) => {
          v.disabled = aFindList.indexOf(v.value) >= 0;
          if (node.auth_code.indexOf(v.value) >= 0 && isEdit) {
            v.disabled = false;
          }
          if (v.value == 'tags' || v.value == 'other') {
            v.disabled = false;
          }
        });
        updateSchema([
          {
            field: 'auth_code',
            componentProps: {
              options: [...tempList],
            },
          },
        ]);
      }

      function fnFindPidList(data, parent_id) {
        let aCodeList: any = [];
        if (isArray(data)) {
          data.forEach((v) => {
            if (v.parent_id == parent_id) {
              aCodeList.push(v.auth_code);
            } else if (v.children) {
              aCodeList = aCodeList.concat(fnFindPidList(v.children, parent_id));
            }
          });
        }
        return aCodeList;
      }

      return {
        getTitle,
        treeRef,
        treeData,
        isUpdate,
        unref,
        actionList,
        registerDrawer,
        registerForm,
        handleSubmit,
        btnEditAccess,
        btnCancel,
        btnAddAccess,
      };
    },
  });
</script>
